/*
 * Copyright (C) 2010 Young, Fey <fey.young@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.youngfey.ebs

import org.junit.*
import static org.junit.Assert.*

/**
 * 
 * @author Young, Fey <fey.young@gmail.com>
 */
class EstimatorTest {
    @Before
    void setUp() {
        histories = []
        def random = new Random()
        20.times { histories << new History(random.nextFloat() * 2, random.nextFloat()) }

        steps = []
        15.times { steps << random.nextFloat() * 20 }
    }

    def histories
    def steps

    // make sure every estimate time is in reasonable range
    def checkRange(idx, value) {
        assertTrue(steps[idx] * histories.collect({it.velocity}).max() >= value)
        assertTrue(steps[idx] * histories.collect({it.velocity}).min() <= value)
    }

    // the avg total time in theory
    def getExpectedAvg() {
        def velocity = 0
        histories.each { velocity += it.velocity * it.weight }
        velocity /= histories.collect({it.weight}).sum()
        steps.sum() * velocity
    }

    def check(rs) {
        checkAvg(rs)
        checkRange(rs)
    }

    def checkAvg(rs) {
        def avg = rs.collect({ it.sum() }).sum() / rs.size()
        assertEquals expectedAvg, avg, expectedAvg / e.weightSteps
    }

    def checkRange(rs) {
        rs.each { result ->
            steps.size().times { checkRange(it, result[it]) }
        }
    }

    def e 
    @Test(timeout=10000L)
    void testEstimate() {
        e = new Estimator()
        e.histories = histories
        e.repeats = 10000
        e.weightSteps = 50

        check(e.estimate(steps))
    }
}
